/*
 * $Id: MplNumber.java,v 1.2 2008/07/10 06:52:05 quy Exp $
 * Copyright(c) 2007-2010 makepolo.com, All Rights Reserved.
 */
package com.util;

import java.math.BigDecimal;
import java.math.BigInteger;

/**
 * ��ֵ������
 * @author xied
 * @version 1.0 2007-11-12
 * @since 1.0
 */
public final class MyNumber {
	
	/** �������ֵ�Ƚ��ַ� */
	private static final String MAX_JAVA_INTEGER_STR = String.valueOf(Integer.MAX_VALUE);
	/** ��С����ֵ�Ƚ��ַ� */
	private static final String MIN_JAVA_INTEGER_STR = String.valueOf(Integer.MIN_VALUE);
	/** �������ֵ���� */
	private static final int MAX_JAVA_INTEGER_LEN = MAX_JAVA_INTEGER_STR.length();
	/** ��С����ֵ���� */
	private static final int MIN_JAVA_INTEGER_LEN = MIN_JAVA_INTEGER_STR.length();
	/** ��������ֵ�Ƚ��ַ� */
	private static final String MAX_JAVA_SHORT_STR = String.valueOf(Short.MAX_VALUE);
	/** ��С������ֵ�Ƚ��ַ� */
	private static final String MIN_JAVA_SHORT_STR = String.valueOf(Short.MIN_VALUE);
	/** ��������ֵ���� */
	private static final int MAX_JAVA_SHORT_LEN = MAX_JAVA_SHORT_STR.length();
	/** ��С������ֵ���� */
	private static final int MIN_JAVA_SHORT_LEN = MIN_JAVA_SHORT_STR.length();
	/** �����ֵ�Ƚ϶��� */
	private static final BigInteger MAX_LONG    = new BigInteger(Long.MAX_VALUE + "");
	/** ��С����ֵ�Ƚ϶��� */
	private static final BigInteger MIN_LONG    = new BigInteger(Long.MIN_VALUE + "");
	/** ��󵥾��ȷ��ֵ�Ƚ϶��� */
	private static final BigDecimal MAX_FLOAT   = new BigDecimal(Float.MAX_VALUE + "");
	/** ��С�����ȷ��ֵ�Ƚ϶��� */
	private static final BigDecimal MIN_FLOAT   = new BigDecimal(Float.MIN_VALUE + "");
	/** ���˫���ȷ��ֵ�Ƚ϶��� */
	private static final BigDecimal MAX_DOUBLE  = new BigDecimal(Double.MAX_VALUE + "");
	/** ��С˫���ȷ��ֵ�Ƚ϶��� */
	private static final BigDecimal MIN_DOUBLE  = new BigDecimal(Double.MIN_VALUE + "");
	/** ƥ����ֵ��������ʾ */
	private static final String NUMBER_PATTERN  = "(\\-?)\\d+(\\.\\d+)?";
	/** ƥ������������ʾ */
	private static final String INTEGER_PATTERN = "(\\-?)\\d+";
	/** ƥ��С���������ʾ */
	private static final String DECIMAL_PATTERN = "(\\-?)\\d+\\.\\d+";
	/** ƥ�������������ʾ */
	private static final String POSITIVE_NUMBER_PATTERN = "\\d+(\\.\\d+)?";
	/** ƥ���������������ʾ */
	private static final String POSITIVE_INTEGER_PATTERN = "\\d+";
	/** ƥ����С���������ʾ */
	private static final String POSITIVE_DECIMAL_PATTERN = "\\d+\\.\\d+";
	/** ƥ�为���������ʾ */
	private static final String NEGATIVE_NUMBER_PATTERN = "-\\d+(\\.\\d+)?";
	/** ƥ�为�����������ʾ */
	private static final String NEGATIVE_INTEGER_PATTERN = "-\\d+";
	/** ƥ�为С���������ʾ */
	private static final String NEGATIVE_DECIMAL_PATTERN = "-\\d+\\.\\d+";

	/**
	 * ���캯��(��)
	 */
	private MyNumber() {}
	
	/**
	 * ���ַ�ת��Ϊint���͵�ֵ
	 * @param input ��ת���ַ�
	 * @return
	 * <li>�ַ����ת��ΪJava������ʱ������ת������ֵ</li>
	 * <li>�����0</li>
	 * @see #getInteger(String, int)
	 */
	public static int getInteger(String input) {
		return getInteger(input, 0);
	}
	/**
	 * ���ַ�ת��Ϊint���͵�ֵ
	 * @param input ��ת���ַ�
	 * @param defVal �޷�ת��ʱ��Ĭ��ֵ
	 * @return
	 * <li>�ַ����ת��ΪJava������ʱ������ת������ֵ</li>
	 * <li>����ز���defVal��ֵ</li>
	 */
	public static int getInteger(String input, int defVal) {
		return isJavaInteger(input) ? Integer.parseInt(input) : defVal;
	}
	/**
	 * �жϴ����ַ��Ƿ����ת��ΪJava����
	 * @param input �����ַ�
	 * @return
	 * <li>true������ת��</li>
	 * <li>false:����ת��</li>
	 */
	public static boolean isJavaInteger(String input) {
		//������
		if (!isInteger(input)) return false;
		//ֵ����
		int len = input.length();
		char ch = input.charAt(0);
		boolean flg = (ch == '-');
		int borderLen = (flg) ? MIN_JAVA_INTEGER_LEN : MAX_JAVA_INTEGER_LEN;
		if (len > borderLen) return false;
		if (len < borderLen) return true;
		String border = (flg) ? MIN_JAVA_INTEGER_STR : MAX_JAVA_INTEGER_STR;
		for (int i = 0; i < len; i++) {
			ch = input.charAt(i);
			char chb = border.charAt(i);
			if (ch == chb) continue;
			return (ch < chb);
		}
		return true;
	}
	
	
	/**
	 * ���ַ�ת��Ϊshort���͵�ֵ
	 * @param input ��ת���ַ�
	 * @return
	 * <li>�ַ����ת��ΪJava������ʱ������ת������ֵ</li>
	 * <li>�����0</li>
	 * @see #getShort(String, short)
	 */
	public static short getShort(String input) {
		return getShort(input, (short)0);
	}
	/**
	 * ���ַ�ת��Ϊshort���͵�ֵ
	 * @param input ��ת���ַ�
	 * @param defVal �޷�ת��ʱ��Ĭ��ֵ
	 * @return
	 * <li>�ַ����ת��ΪJava������ʱ������ת������ֵ</li>
	 * <li>����ز���defVal��ֵ</li>
	 */
	public static short getShort(String input, short defVal) {
		return isShort(input) ? Short.parseShort(input) : defVal;
	}
	/**
	 * �жϴ����ַ��Ƿ����ת��ΪJava������
	 * @param input �����ַ�
	 * @return
	 * <li>true������ת��</li>
	 * <li>false:����ת��</li>
	 */
	public static boolean isShort(String input) {
		//������
		if (!isInteger(input)) return false;
		//ֵ����
		int len = input.length();
		char ch = input.charAt(0);
		boolean flg = (ch == '-');
		int borderLen = (flg) ? MIN_JAVA_SHORT_LEN : MAX_JAVA_SHORT_LEN;
		if (len > borderLen) return false;
		if (len < borderLen) return true;
		String border = (flg) ? MIN_JAVA_SHORT_STR : MAX_JAVA_SHORT_STR;
		for (int i = 0; i < len; i++) {
			ch = input.charAt(i);
			char chb = border.charAt(i);
			if (ch == chb) continue;
			return (ch < chb);
		}
		return true;
	}
	
	/**
	 * ���ַ�ת��Ϊbyte���͵�ֵ
	 * @param input ��ת���ַ�
	 * @return
	 * <li>�ַ����ת��Ϊbyteֵʱ������ת������ֵ</li>
	 * <li>�����0</li>
	 * @see #getByte(String, byte)
	 */
	public static byte getByte(String input) {
		return getByte(input, (byte)0);
	}
	/**
	 * ���ַ�ת��Ϊbyte���͵�ֵ
	 * @param input ��ת���ַ�
	 * @param defVal �޷�ת��ʱ��Ĭ��ֵ
	 * @return
	 * <li>�ַ����ת��Ϊbyteֵʱ������ת������ֵ</li>
	 * <li>����ز���defVal��ֵ</li>
	 */
	public static byte getByte(String input, byte defVal) {
		return isByte(input) ? Byte.parseByte(input) : defVal;
	}
	/**
	 * �жϴ����ַ��Ƿ����ת��Ϊbyteֵ
	 * @param input �����ַ�
	 * @return
	 * <li>true������ת��</li>
	 * <li>false:����ת��</li>
	 */
	public static boolean isByte(String input) {
		if (input == null || !input.matches(INTEGER_PATTERN)) return false;
		if (input.length() > 4) return false;
		int tmp = Integer.parseInt(input);
		return (tmp <= Byte.MAX_VALUE && tmp >= Byte.MIN_VALUE);
	}
	
	/**
	 * ���ַ�ת��Ϊlong���͵�ֵ
	 * @param input ��ת���ַ�
	 * @return
	 * <li>�ַ����ת��Ϊlongֵʱ������ת������ֵ</li>
	 * <li>�����0L</li>
	 * @see #getLong(String, long)
	 */
	public static long getLong(String input) {
		return getLong(input, 0L);
	}
	/**
	 * ���ַ�ת��Ϊlong���͵�ֵ
	 * @param input ��ת���ַ�
	 * @param defVal �޷�ת��ʱ��Ĭ��ֵ
	 * @return
	 * <li>�ַ����ת��Ϊlongֵʱ������ת������ֵ</li>
	 * <li>����ز���defVal��ֵ</li>
	 */
	public static long getLong(String input, long defVal) {
		return isLong(input) ? Long.parseLong(input) : defVal;
	}
	/**
	 * �жϴ����ַ��Ƿ����ת��Ϊlongֵ
	 * @param input �����ַ�
	 * @return
	 * <li>true������ת��</li>
	 * <li>false:����ת��</li>
	 */
	public static boolean isLong(String input) {
		if (input == null || !input.matches(INTEGER_PATTERN)) return false;
		BigInteger bi = new BigInteger(input);
		return (bi.compareTo(MIN_LONG) >= 0 && bi.compareTo(MAX_LONG) <= 0);
	}
	
	/**
	 * ���ַ�ת��Ϊfloat���͵�ֵ
	 * @param input ��ת���ַ�
	 * @return
	 * <li>�ַ����ת��Ϊfloatֵʱ������ת������ֵ</li>
	 * <li>�����0.0f</li>
	 * @see #getFloat(String, float)
	 */
	public static float getFloat(String input) {
		return getFloat(input, 0.0f);
	}
	/**
	 * ���ַ�ת��Ϊfloat���͵�ֵ
	 * @param input ��ת���ַ�
	 * @param defVal �޷�ת��ʱ��Ĭ��ֵ
	 * @return
	 * <li>�ַ����ת��Ϊfloatֵʱ������ת������ֵ</li>
	 * <li>����ز���defVal��ֵ</li>
	 */
	public static float getFloat(String input, float defVal) {
		return isFloat(input) ? Float.parseFloat(input) : defVal;
	}
	/**
	 * �жϴ����ַ��Ƿ����ת��Ϊfloatֵ
	 * @param input �����ַ�
	 * @return
	 * <li>true������ת��</li>
	 * <li>false:����ת��</li>
	 */
	public static boolean isFloat(String input) {
		if(!isNumber(input)) return false;
		BigDecimal bd = new BigDecimal(input);
		return (bd.compareTo(MIN_FLOAT) >= 0 && bd.compareTo(MAX_FLOAT) <= 0);
	}
	
	/**
	 * ���ַ�ת��Ϊdouble���͵�ֵ
	 * @param input ��ת���ַ�
	 * @return
	 * <li>�ַ����ת��Ϊdoubleֵʱ������ת������ֵ</li>
	 * <li>�����0.0</li>
	 * @see #getDouble(String, double)
	 */
	public static double getDouble(String input) {
		return getDouble(input, 0.0);
	}
	/**
	 * ���ַ�ת��Ϊdouble���͵�ֵ
	 * @param input ��ת���ַ�
	 * @param defVal �޷�ת��ʱ��Ĭ��ֵ
	 * @return
	 * <li>�ַ����ת��Ϊdoubleֵʱ������ת������ֵ</li>
	 * <li>����ز���defVal��ֵ</li>
	 */
	public static double getDouble(String input, double defVal) {
		return isDouble(input) ? Double.parseDouble(input) : defVal;
	}
	/**
	 * �жϴ����ַ��Ƿ����ת��Ϊdoubleֵ
	 * @param input �����ַ�
	 * @return
	 * <li>true������ת��</li>
	 * <li>false:����ת��</li>
	 */
	public static boolean isDouble(String input) {
		if(!isNumber(input)) return false;
		BigDecimal bd = new BigDecimal(input);
		return (bd.compareTo(MIN_DOUBLE) >= 0 && bd.compareTo(MAX_DOUBLE) <= 0);
	}
	
	/**
	 * ���ַ�ת��Ϊboolean���͵�ֵ
	 * @param input ��ת���ַ�
	 * @return
	 * <li>�ַ����ת��Ϊbooleanֵʱ������ת���󲼶�ֵ</li>
	 * <li>�����false</li>
	 * @see #getBoolean(String, boolean)
	 */
	public static boolean getBoolean(String input) {
		return getBoolean(input, false);
	}
	/**
	 * ���ַ�ת��Ϊboolean���͵�ֵ
	 * @param input ��ת���ַ�
	 * @param defVal �޷�ת��ʱ��Ĭ��ֵ
	 * @return
	 * <li>�ַ����ת��Ϊbooleanֵʱ������ת���󲼶�ֵ</li>
	 * <li>����ز���defVal��ֵ</li>
	 */
	public static boolean getBoolean(String input, boolean defVal) {
		Boolean bln = parseMplBoolean(input);
		return (bln == null) ? defVal : bln;
	}
	/**
	 * ���ַ�ת��Ϊ����ֵ��<br/>
	 * ת������<br/>
	 * <li>�ַ�Ϊ"true"ʱ(����ִ�Сд)������true</li>
	 * <li>�ַ�Ϊ�����Ҳ�Ϊ"0"ʱ������true</li>
	 * <li>�ַ�Ϊ"false"ʱ(����ִ�Сд)������false</li>
	 * <li>�ַ�Ϊ"0"ʱ������false</li>
	 * <li>�����null</li>
	 * @param input ��ת���ַ�
	 * @return
	 * <li>����ת��ʱ������ת�����ֵ</li>
	 * <li>�޷�ת��ʱ������null</li>
	 */
	private static Boolean parseMplBoolean(String input) {
		if (input == null) return null;
		if (input.equalsIgnoreCase("true")) return true;
		if (input.equalsIgnoreCase("false")) return false;
		if (matchesNumber(input, NUMBER_PATTERN)) {
			return  !"0".equals(input);
		}
		return null;
	}
	
	/**
	 * ����ַ��Ƿ����ת��Ϊ��ֵ
	 * @param input �����ַ�
	 * @return
	 * <li>true������ת������ֵ</li>
	 * <li>false������ת������ֵ</li>
	 */
	public static boolean isNumber(String input) {
		return matchesNumber(input, NUMBER_PATTERN);
	}
	/**
	 * ����ַ��Ƿ����������
	 * <B>Ч����������ʾ����20-60��</B>
	 * @param input �����ַ�
	 * @return
	 * <li>true��������</li>
	 * <li>false����������</li>
	 */
	public static boolean isInteger(String input) {
		if (input == null) return false;
		int len = input.length();
		if (len == 0) return false;
		char ch = input.charAt(0);
		if (ch != '-' && (ch < '0' || ch > '9')) return false;
		for (int i = 1; i< len; i++) {
			ch = input.charAt(i);
			if (ch < '0' && ch > '9') return false;
		}
		return true;
	}
	/**
	 * ����ַ��Ƿ���С��
	 * @param input �����ַ�
	 * @return
	 * <li>true����С��</li>
	 * <li>false������С��</li>
	 */
	public static boolean isDecimal(String input) {
		return matchesNumber(input, DECIMAL_PATTERN);
	}
	/**
	 * ����ַ��Ƿ�������
	 * @param input �����ַ�
	 * @return
	 * <li>true��������</li>
	 * <li>false����������</li>
	 */
	public static boolean isPositiveNumber(String input) {
		return matchesNumber(input, POSITIVE_NUMBER_PATTERN);
	}
	/**
	 * ����ַ��Ƿ���������
	 * @param input �����ַ�
	 * @return
	 * <li>true����������</li>
	 * <li>false������������</li>
	 */
	public static boolean isPositiveInteger(String input) {
		return matchesNumber(input, POSITIVE_INTEGER_PATTERN);
	}
	/**
	 * ����ַ��Ƿ�����С��
	 * @param input �����ַ�
	 * @return
	 * <li>true������С��</li>
	 * <li>false��������С��</li>
	 */
	public static boolean isPositiveDecimal(String input) {
		return matchesNumber(input, POSITIVE_DECIMAL_PATTERN);
	}
	/**
	 * ����ַ��Ƿ��Ǹ���
	 * @param input �����ַ�
	 * @return
	 * <li>true���Ǹ���</li>
	 * <li>false�����Ǹ���</li>
	 */
	public static boolean isNegativeNumber(String input) {
		return matchesNumber(input, NEGATIVE_NUMBER_PATTERN);
	}
	/**
	 * ����ַ��Ƿ��Ǹ�����
	 * @param input �����ַ�
	 * @return
	 * <li>true���Ǹ�����</li>
	 * <li>false�����Ǹ�����</li>
	 */
	public static boolean isNegativeInteger(String input) {
		return matchesNumber(input, NEGATIVE_INTEGER_PATTERN);
	}
	/**
	 * ����ַ��Ƿ��Ǹ�С��
	 * @param input �����ַ�
	 * @return
	 * <li>true���Ǹ�С��</li>
	 * <li>false�����Ǹ�С��</li>
	 */
	public static boolean isNegativeDecimal(String input) {
		return matchesNumber(input, NEGATIVE_DECIMAL_PATTERN);
	}
	/**
	 * ����ַ�ƥ��
	 * @param input �����ַ�
	 * @param pattern ƥ�����
	 * @return
	 * <li>true���ַ�Ϊnull������pattern����ָ������ƥ��</li>
	 * <li>false������</li>
	 */
	private static boolean matchesNumber(String input, String pattern) {
		return (input != null && input.matches(pattern));
	}
	
	/**
	 * ���ַ�ת��ΪBigDecimal���Ͷ���
	 * @param input ��ת���ַ�
	 * @return
	 * <li>�ַ�����Ϊ��ֵʱ������ת�������</li>
	 * <li>�����null</li>
	 * @see #getBigDecimal(String, BigDecimal)
	 */
	public static BigDecimal getBigDecimal(String input) {
		return getBigDecimal(input, null);
	}
	/**
	 * ���ַ���ΪBigDecimal���Ͷ���
	 * @param input ��ת���ַ�
	 * @param defVal �޷�ת��ʱĬ�Ϸ���ֵ
	 * @return
	 * <li>�ַ���������ֵʱ������ת�������</li>
	 * <li>�����null</li>
	 * @see #getBigDecimal(String)
	 */
	public static BigDecimal getBigDecimal(String input, BigDecimal defVal) {
		return isNumber(input) ? new BigDecimal(input) : defVal;
	}
	
	/**
	 * ���ַ�ת��ΪBigInteger���Ͷ���
	 * @param input ��ת���ַ�
	 * @return
	 * <li>�ַ�����Ϊ��ֵʱ������ת�������</li>
	 * <li>�����null</li>
	 * @see #getBigInteger(String, BigInteger)
	 */
	public static BigInteger getBigInteger(String input) {
		return getBigInteger(input, null);
	}
	/**
	 * ���ַ���ΪBigInteger���Ͷ���
	 * @param input ��ת���ַ�
	 * @param defVal �޷�ת��ʱĬ�Ϸ���ֵ
	 * @return
	 * <li>�ַ���������ֵʱ������ת�������</li>
	 * <li>�����null</li>
	 * @see #getBigInteger(String)
	 */
	public static BigInteger getBigInteger(String input, BigInteger defVal) {
		return isInteger(input) ? new BigInteger(input) : defVal;
	}
}
